(in-package :pollster)

(enable-sql-reader-syntax)
(start-sql-recording)

(connect `(nil "pollster" "admin" "faster1")
	 :database-type :mysql)

(defun get-poll-title (id)
  "Returns either the poll title for a given ID or nil"
  (caar (select [question] :from "poll"
		:where [= [id] id])))

(defun get-poll-choices (id)
  "Return a list of the choices for a poll with a given ID"
  (let ((text-representation (caar (select [answers] :from "poll"
					   :where [= [id] id])))
	(*read-eval* nil))
    (when text-representation
      (values (read-from-string text-representation nil nil)))))

(defun print-poll-choices (id)
  (loop for choice in (get-poll-choices id)
	for choice-number = 0 then (1+ choice-number)
	do (with-html-output (*standard-output*)
	     (:input :type "radio"
		     :name "choice"
		     :value (str choice-number))
	     (esc choice)
	     (:br))))

(defun print-poll-results (id)
  "Print the poll results"
  (with-html-output (*standard-output*)
    (:table
     (loop for choice in (get-poll-choices id)
	   for choice-number = 0 then (1+ choice-number)
	   do (let ((choice-count (get-choice-count id choice-number))
		    (total-votes (get-total-votes id)))
		(with-html-output (*standard-output*)
		  (:tr (:td (esc choice))
		       (:td (:img :src "/blue14.png" :height "14"
				  :width (str (round (* (/ choice-count
							   total-votes)
							500)))))
		       (:td (str choice-count)))))))))

(defun get-choice-count (id choice-number)
  "Return the number of people who voted for a given choice on a poll
with the given id."
  (caar (select [count [*]] :from "votes"
		:where [and [= [id] id]
			    [= [choice] choice-number]])))

(defun get-total-votes (id)
  "Get the total number of votes cast on a given poll"
  (caar (select [count [*]] :from "votes"
		:where [= [id] id])))

(defun current-poll-id ()
  "Return the ID of the latest poll"
  (caar (select [max [id]] :from "poll")))

(defun valid-poll-id-p (id)
  "Is a poll ID valid?"
  (<= id (current-poll-id)))

(defun record-vote (id)
  "Record a vote with a given ID using the request environment to get
the choice."
  (insert-records :into "votes"
		  :attributes '(id choice)
		  :values (list id (parse-integer (parameter "choice")))))

(defun split-crlf (string)
  "Split string, delimited by CR-LF pairs"
  (cl-ppcre:split "?
" string))

(defun do-create-poll ()
  (let* ((choices (print (parameter "choices")))
	 (question (parameter "question")))
    (if (and choices question)
	(let ((choices-list (print (split-crlf choices))))
	  (insert-records :into "poll"
			  :attributes '(question answers)
			  :values (list question
					(format nil "~S" choices-list)))
	  (with-html
	    (:html (:head (:title "Pollster | Poll created"))
		   (:body (:h1 "Poll created")
			  (:a :href (format nil "/tbnl/pollster-front-page.tbnl?id=~D"
					    (current-poll-id))
			      "View poll")))))
	(with-html
	  (:html (:head (:title "Pollster | Poll NOT created!"))
		 (:body (:h1 "Poll NOT created!")
			(:p "Your poll was not created, because of the
following problems:")
			(unless question
			  (htm (:p "You didn't fill in the question.")))
			(unless choices
			  (htm (:p "You didn't fill in the choices.")))))))))